package com.eianiao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eianiao.bean.Category;
import com.eianiao.bean.Dish;
import com.eianiao.bean.DishFlavor;
import com.eianiao.bean.Setmeal;
import com.eianiao.common.PageParam;
import com.eianiao.dao.DishDao;
import com.eianiao.dto.DishDto;
import com.eianiao.exception.CustomException;
import com.eianiao.service.CategoryService;
import com.eianiao.service.DishFlavorService;
import com.eianiao.service.DishService;
import com.eianiao.service.SetmealDishService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author eianiao
 * @Date 2022 06
 * @Version 1.0
 **/
@Service
@Transactional
public class DishServiceImpl implements DishService {

    @Autowired
    private DishDao dishDao;


    @Autowired
    private DishFlavorService dishFlavorService;

    @Lazy
    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SetmealDishService setmealDishService;


    /**
     * 根据分类菜品的id，查询出来该分类的所有菜品
     *
     * @param categoryId
     * @return
     */
    @Override
    public List<DishDto> findByCategoryId(Long categoryId,Integer status,String name) {
        LambdaQueryWrapper<Dish> qw = new LambdaQueryWrapper<>();
        qw.eq(categoryId!=null,Dish::getCategoryId,categoryId);
        qw.eq(status !=null, Dish::getStatus,status);
        qw.eq(name!=null,Dish::getName,name);
        List<Dish> dishList = dishDao.selectList(qw);
        //4. 要包装每一个菜品和口味数据
        return dishList.stream().map(dish->{

            //4.1 创建DishDto对象
            DishDto dto = new DishDto();

            //4.2 根据菜品的id，去查询这个菜品的口味数据
            List<DishFlavor> flavorList = dishFlavorService.findByDishId(dish.getId());

            //4.3 封装数据： 把口味数据封装到dto里面
            dto.setFlavors(flavorList);

            //4.4 封装数据： 把菜品数据封装到dto里面
            BeanUtils.copyProperties(dish , dto);

            //4.5 返回dto
            return dto;
        }).collect(Collectors.toList());
    }

    /**
     * 添加菜品
     * @param dishDto
     * @return
     */
    @Override
    public int add(DishDto dishDto) {

        //1. 往菜品表里面添加数据
        int row = dishDao.insert(dishDto);

        //2. 往口味表添加数据
        //只有当菜品表添加成功了，并且这个菜品是有口味数据的，才执行这段if操作，否则不执行这段操作！
        if(row > 0 && dishDto.getFlavors()!= null && dishDto.getFlavors().size() > 0 ){

            int row2 = 0 ;

            for (DishFlavor flavor : dishDto.getFlavors()) {

                //设置口味属于哪一种菜
                flavor.setDishId(dishDto.getId());

                //把每一个口味数据，添加到口味表！
                row2 += dishFlavorService.add(flavor);
            }
            return row2 ==  dishDto.getFlavors().size() ? 1 : 0;
        }

        return row;
    }


    /**
     * 分页查询
     *      1. 先把菜品的分页数据给查询出来。但是不能直接就返回菜品数据。这是不够页面展示用的
     *      2. 上面的步骤是直接去查询菜品表，那么会缺少两个数据：  分类的名称 和 口味的数据
     *      3. 要想把分类的名称和口味的数据也查询出来，必须得去查询分类表和口味表
     *          3.1 查询到了菜品的数据【集合】之后，遍历每一个菜品，得到菜品的分类id值，拿着分类的id值去查询分类表
     *              得到了之后，和菜品数据一起打包！
     *          3.2 查询到了菜品的数据【集合】之后，遍历每一个菜品，得到菜品的id值，拿着菜品的id值去查询口味表
     *              得到数据之后，也要和菜品数据一起打包！
     *          3.3 此时可以使用DishDto 来包装这是三个数据： dish本身的数据， 分类名称， 口味数据
     *
     *          3.4 这也就意味着一会分页查询Dish表 得到 IPage<Dish> 这个结果不能直接返回给controller 应该返回
     *              IPage<DishDto>
     *
     *          3.5 这里唯一比较棘手的就是遍历IPage<Dish> 打散内容，封装成IPage<DishDto>
     * @param pageParam
     * @return
     */
    @Override
    public IPage<DishDto> findPage(PageParam pageParam) {

        //1. 构建分页配置
        IPage<Dish> p = new Page<>(pageParam.getPage(), pageParam.getPageSize());

        //2. 定义查询条件
        LambdaQueryWrapper<Dish> qw =new LambdaQueryWrapper<>();

        //2.1 设置条件
        qw.like( pageParam.getName() != null , Dish::getName , pageParam.getName());

        //3. 执行分页
        IPage<Dish> dishIPage = dishDao.selectPage(p, qw);

        //==上面已经把菜品的集合数据查询出来了，但是不能返回它，因为它的数据不充分，要补充数据===

        //4. 遍历每一个菜品
        List<DishDto> dtoList = dishIPage.getRecords().stream().map((dish)->{
            //4.1 查询分类
            Category category = categoryService.findById(dish.getCategoryId());

            //4.2 查询口味
            List<DishFlavor> flavorList = dishFlavorService.findByDishId(dish.getId());

            //4.3 把 dish 和 分类名称 和 口味集合数据 组装成一个全新的对象 DishDto
            DishDto dishDto = new DishDto();
            //4.3.1 填充分类名称
            dishDto.setCategoryName(category.getName());

            //4.3.2 填充口味数据
            dishDto.setFlavors(flavorList);

            //4.3.3 填充菜品数据
            //dishDto.setId(dish.getId());
            //dishDto.setName(dish.getName());
            //dishDto.setImage(dish.getImage());
            //使用工具方法来拷贝同名的属性，从dise身上拷贝到dishDto身上
            BeanUtils.copyProperties(dish , dishDto);

            return dishDto;
        }).collect(Collectors.toList());

        //5. 构建IPage<DishDto> 然后返回
        IPage<DishDto> dtoIPage = new Page<>();

        //5.1 设置集合数据
        dtoIPage.setRecords(dtoList);

        //5.2 设置总记录数
        dtoIPage.setTotal(dishIPage.getTotal());

        return dtoIPage;
    }

    /**
     * 更新菜品
     *
     * @param dishDto
     * @return
     */
    @Override
    public int update(DishDto dishDto) {
        int row1 = dishDao.updateById(dishDto);
        if (row1 > 0){
            dishFlavorService.deleteByDishId(dishDto.getId());
            List<DishFlavor> flavors = dishDto.getFlavors();
            if (flavors != null && flavors.size() >0){
                int row2 = 0;
                for (DishFlavor dishFlavor : flavors) {
                    dishFlavor.setDishId(dishDto.getId());
                    row2 += dishFlavorService.add(dishFlavor);
                }
                return row2 == flavors.size()? 1 : 0;
            }
        }

        return row1;
    }


    /**
     * 停售.启售+批量
     *
     * @param statusId
     * @param ids
     * @return
     */
    @Override
    public int updateById(int statusId, List<Long> ids) {
        //需要构建条件
        LambdaQueryWrapper<Dish> qw = new LambdaQueryWrapper<>();
        qw.in(Dish::getId,ids);
        List<Dish> dishList = dishDao.selectList(qw);
        int row = 0;
        if (dishList != null){
            for (Dish dish : dishList) {
                dish.setStatus(statusId);
                row = dishDao.updateById(dish);
            }
        }
        return row > 0 ? 1 : 0;
    }


    /**
     * 删除菜品或者批量删除
     *
     * @param ids
     * @return
     */
    @Override
    public int deleteById(List<Long> ids) {
        //根据id进行删除菜品时，需要删除关于这个菜品的口味dish_flavor和套餐的菜品setmeal_dish
        //0.先判断ids是不是空，空就直接返回
        int row = 0;
        if (ids ==null){
            return row;
        }
        //删除停售状态的菜品
        //1.1先查询要删除的菜品
        LambdaQueryWrapper<Dish> qw = new LambdaQueryWrapper<>();
        qw.in(Dish::getId,ids);
        qw.eq(Dish::getStatus , 1);
        int total = dishDao.selectCount(qw);
        if(total > 0 ) {
            throw new CustomException("菜品处于启售状态，禁止删除！");
        }
        //1.2删除停售的菜品
        row = dishDao.deleteBatchIds(ids);
        //2.删除菜品关联的口味（口味有个dish_id）和套餐(套餐有个setmeal_id和dish_id)要查出来
        //2.1要根据菜品id查两个id
        //2.2根据两个id进行删除（调用其他两个service干活）
        for (Long id : ids) {
            dishFlavorService.deleteByDishId(id);
            setmealDishService.deleteByDishId(id);
        }


        return row > 0 ? 1 : 0;
    }


}
